import { AsyncComponentLoader } from 'vue'
import { RouteRecordRaw, Router } from 'vue-router'
import { ButtonRouteMeta } from './routeinfo'
import { LoginUserMenuItem, MENUTYPE, OPENTYPE } from '@/api'

export const modules: Record<string, AsyncComponentLoader> = import.meta.glob('../pages/**/*.vue')
function getModule(params: string): AsyncComponentLoader {
  const tp = params.replace(/^\//, '')
  const key: string = `../pages/${tp}.vue`
  const moduleFunction: AsyncComponentLoader = modules[key]
  return moduleFunction
}
const ExternalLinks = getModule('/external-links/index')
const DefaultRouteView = getModule('/view-wrapper/default-routre-view')

const HttpLinkReg: RegExp = /^https?:\/\/[a-zA-Z\d]{2,}\.[a-zA-Z\d.]+$/i
const ComponentFieldReg = /^[a-zA-Z/]{2,}/i
class RouteTool {
  public buttons: ButtonRouteMeta[]
  public formatedTree: LoginUserMenuItem[]
  constructor(routeTree: LoginUserMenuItem[], ...args: any[]) {
    this.buttons = this.collectButton(routeTree)
    this.formatedTree = routeTree
  }
  /**
   * 
   * @param {LoginUserMenuItem[]} routeTree 后端返回的原始树形数组
   * @returns {ButtonRouteMeta[]} 按钮数组
   */
  private collectButton(routeTree: LoginUserMenuItem[] = this.formatedTree): ButtonRouteMeta[] {
    return routeTree.reduce((pre, curr) => {
      if (curr.type === MENUTYPE.BUTTON) {
        const { id, code, name, application, type, router, visible, permission, openType, link } = curr
        pre.push({ id, code, name, application, type, router, visible, permission, openType, link })
      }
      if (curr.children && curr.children.length) {
        return pre.concat(this.collectButton(curr.children))
      }
      return pre
    }, [] as ButtonRouteMeta[])
  }
  /**
   * 将原始路由记录格式化为可被uerouter直接使用的配置信息
   * 如果是外部连
   * @param {LoginUserMenuItem} route 原始路由记录
   * @returns {RouteRecordRaw}
   */
  private formatRoute(route: LoginUserMenuItem): RouteRecordRaw | null {
    const { component, code, router, openType, type, link, children, redirect, icon, name, id } = route
    const meta = { code, id, name, icon, openType, link, type }
    const wasDIr = type === MENUTYPE.DIR, wasLink = (openType === OPENTYPE.InnerLink)
    const formatLink = (link || '').trim()
    const routeName = router && router.trim().replace(/^\//, '').replaceAll('/', '-')
    const routeComponent = component.trim().replace(/^\//, '')
    // 处理连接和空组件值
    if ((openType === OPENTYPE.OuterLink) && !ComponentFieldReg.test(routeComponent)) {
      return null
    }
    if (wasLink) {
      if (!formatLink) return null
      const urlobj = new URL(formatLink)
      const path = urlobj.pathname.replace(/^\//, '')
      const name = path.replace(/\//g, '-')
      if (HttpLinkReg.test(formatLink)) {
        return { name, path, component: ExternalLinks, props: { link: formatLink }, meta }
      }
      return { path, name, redirect: path, meta }
    }
    // 处理连接结束
    const routeconfig: RouteRecordRaw = {
      path: router.trim(),
      name: routeName,
      component: getModule(`/${routeComponent}`),
      meta,
    }
    if (wasDIr) {
      Object.assign(routeconfig, { redirect, component: routeconfig.component || DefaultRouteView, })
    } else {
      Object.assign(routeconfig, { component: routeconfig.component || getModule('/system/errorPage/404'), })
    }
    return routeconfig
  }
  public getRouteConfig(routes: LoginUserMenuItem[] = this.formatedTree): RouteRecordRaw[] {
    return routes.filter(item => MENUTYPE.BUTTON !== item.type)
      .map((info) => {
        const { children } = info
        const route = this.formatRoute(info)
        if (route && Array.isArray(info.children)) {
          const chil = this.getRouteConfig(children)
          route.children = chil
        }
        return route
      })
      .filter(v => !!v) as RouteRecordRaw[]
  }

}
export { getModule, RouteTool }

export function getDetaultIndex(router: Router) {
  const dynamics = router.getRoutes();
  let homeRoute = dynamics.find((i) =>
    /(home)/i.test(i.name as string)
  );
  // 如果存在应用存在home路径,那么就跳转home
  if (homeRoute) {
    return homeRoute
  } else if (Array.isArray(dynamics) && dynamics.length) {
    // 直接搜索
    const f = dynamics.filter(i => i.meta.type === '1').at(0)
    return f
  }
}